#include "AudioRecorder.h"
#include "ui_AudioRecorder.h"
#include <QMessageBox>
#include <QFile>
#include <QUrl>
#include <QAudioFormat>
#include <QFileDialog>
#include <QFileInfo>

AudioRecorder::AudioRecorder(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::AudioRecorder)
{
    ui->setupUi(this);

    m_pAudioRecorder = new QAudioRecorder (this) ;
    connect(m_pAudioRecorder, &QAudioRecorder::stateChanged, this, &AudioRecorder::onStateChanged);
    connect (m_pAudioRecorder, &QAudioRecorder::durationChanged, this, &AudioRecorder::onDurationChanged);

    m_pAudioProbe = new QAudioProbe; //探测器
    connect(m_pAudioProbe, &QAudioProbe::audioBufferProbed, this, &AudioRecorder::processBuffer);
    m_pAudioProbe->setSource (m_pAudioRecorder) ;

    //返回默认的音频输入名称。如果是空则return
    if (m_pAudioRecorder->defaultAudioInput().isEmpty())
    {
        return;  //无音频输入设备
    }

    //返回可用音频输入的列表
    for (const QString &device: m_pAudioRecorder->audioInputs())
    {
        ui->comboxDevices->addItem (device); //音频输入设备列表
    }
    //返回支持的音频编解码器列表。
    for (const QString &codecName: m_pAudioRecorder->supportedAudioCodecs () )
    {
        ui->comboxCodec->addItem (codecName) ; //支持的音频编码
    }
    //返回支持的音频采样率列表。
    for (int sampleRate:m_pAudioRecorder->supportedAudioSampleRates())
    {
        ui->comboxSampleRate->addItem (QString::number(sampleRate)); //采样率
    }

    //channels 通道
    ui->comboxChannels->addItem("1") ;
    ui->comboxChannels->addItem("2") ;
    ui->comboxChannels->addItem("4") ;
    //quality 品质
    ui->sliderQuality->setRange(0, int(QMultimedia::VeryHighQuality)) ;
    ui->sliderQuality->setValue(int(QMultimedia::NormalQuality)) ;

    //bitrates 比特率
    ui->comboxBitrate->addItem("32000") ;
    ui->comboxBitrate->addItem("64000") ;
    ui->comboxBitrate->addItem("96000") ;
    ui->comboxBitrate->addItem("128000") ;

}

AudioRecorder::~AudioRecorder()
{
    delete ui;
}

void AudioRecorder::onStateChanged(QMediaRecorder::State state)
{
    //录音状态发生变化后
    ui->btnRecord->setEnabled(state !=QMediaRecorder::RecordingState) ;
    ui->btnPause->setEnabled(state==QMediaRecorder::RecordingState) ;
    ui->btnStop->setEnabled(state==QMediaRecorder::RecordingState) ;
    ui->btnGetFile->setEnabled(state==QMediaRecorder::StoppedState) ;
    ui->editOutputFile->setEnabled(state==QMediaRecorder::StoppedState) ;
}

void AudioRecorder::onDurationChanged(qint64 duration)
{
    //录音持续时间变化
    ui->LabPassTime->setText(QString("已录制%1秒").arg(duration / 1000) ) ;
}

void AudioRecorder::processBuffer(const QAudioBuffer &buffer)
{
    //处理探测到的缓冲区
    ui->spin_byteCount->setValue(buffer.byteCount());//缓冲区字节数
    ui->spin_duration->setValue(buffer.duration() /1000);//缓冲区时长
    ui->spin_frameCount->setValue(buffer.frameCount());//缓冲区帧数
    ui->spin_sampleCount->setValue(buffer.sampleCount()) ;//缓冲区采样数
    QAudioFormat audioFormat=buffer.format() ; //缓冲区格式
    ui->spin_channelCount->setValue(audioFormat. channelCount()) ; //通道数
    ui->spin_sampleSize->setValue(audioFormat. sampleSize()) ;//采样大小
    ui ->spin_sampleRate->setValue(audioFormat. sampleRate()) ;//采样率
    ui ->spin_bytesPerFrame->setValue(audioFormat .bytesPerFrame()) ;
    if (audioFormat.byteOrder() == QAudioFormat::LittleEndian)
    {
          ui->edit_byteOrder->setText ("LittleEndian");//字节序.
    }
    else
    {
        ui->edit_byteOrder->setText ("BigEndian") ;
    }

    ui->edit_codec->setText(audioFormat.codec()) ; //编码格式
    if (audioFormat. sampleType ()==QAudioFormat::SignedInt) //采样点类型
    {
        ui ->edit_sampleType->setText ("SignedInt") ;
    }
    else if (audioFormat.sampleType() == QAudioFormat::UnSignedInt)
    {
        ui ->edit_sampleType->setText ("UnSignedInt") ;
    }
    else if (audioFormat.sampleType() == QAudioFormat::Float)
    {
        ui->edit_sampleType->setText("Float") ;
    }
    else{
        ui->edit_sampleType->setText("Unknown") ;
    }
}


void AudioRecorder::on_btnRecord_clicked()
{
    if (m_pAudioRecorder->state() == QMediaRecorder::StoppedState) //已停止， 重新设置
    {
           QString selectedFile=ui->editOutputFile->text() .trimmed() ;
           if (selectedFile.isEmpty())
           {
                QMessageBox::critical (this, "错误", "请先设置录音输出文件");
                return;
           }
            if (QFile::exists(selectedFile))
            {
                if (!QFile::remove(selectedFile) ){
                    QMessageBox::critical (this, "错误", "所设置录音输出文件无法删除") ;
                    return;
                }
            }

            m_pAudioRecorder->setOutputLocation (QUrl::fromLocalFile (selectedFile)) ;
            m_pAudioRecorder->setAudioInput(ui->comboxDevices->currentText()); //输入设备
            QAudioEncoderSettings settings; // 音频编码设置
            settings.setCodec(ui->comboxCodec->currentText()) ; //编码
            settings.setSampleRate(ui->comboxSampleRate->currentText().toInt()) ;
            settings.setBitRate(ui->comboxBitrate->currentText().toInt()) ;//比特率
            settings.setChannelCount(ui->comboxChannels->currentText().toInt()) ;
            settings.setQuality(QMultimedia::EncodingQuality (ui ->sliderQuality->value())) ;
            if (ui->radioQuality->isChecked()) //编码模式为固定品质
            {
                 settings.setEncodingMode(QMultimedia::ConstantQualityEncoding) ;
            }
            else
            {
                settings.setEncodingMode(QMultimedia::ConstantBitRateEncoding) ;

            }
            m_pAudioRecorder->setAudioSettings(settings) ; //音频设置
    }

    m_pAudioRecorder->record() ;
}

void AudioRecorder::on_btnPause_clicked()
{
    m_pAudioRecorder->pause();
}

void AudioRecorder::on_btnStop_clicked()
{
    m_pAudioRecorder->stop();
}

void AudioRecorder::on_btnGetFile_clicked()
{
    QString file_full, file_name, file_path;
      QFileInfo fi;//文件路径
  //    file_full = QFileDialog::getOpenFileName(this);
  //      打开文件        获取文件路径
      file_full = QFileDialog::getSaveFileName(this,tr("Save File"),tr("*.wav"));
  //      保存文件        获取文件路径  “Save File” 对话框名        “*.wav 默认文件名
      fi= QFileInfo(file_full);

  //      显示文件路径
      file_name = fi.fileName();
      file_path = fi.absolutePath();
      ui->editOutputFile->setText(file_path+"\\"+file_name);
}

void AudioRecorder::on_btnQuit_clicked()
{
    QApplication::quit();
}
